package com.longkey.workflow.client.canvas
{
	import com.longkey.workflow.client.constants.AnchorType;
	import com.longkey.workflow.client.constants.ElementType;
	import com.longkey.workflow.client.constants.StatusType;
	import com.longkey.workflow.client.control.Context;
	import com.longkey.workflow.client.event.PropertyEvent;
	import com.longkey.workflow.client.util.MathUtil;
	
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.ui.MouseCursor;
	import flash.utils.getQualifiedClassName;
	
	import mx.collections.ArrayCollection;
	import mx.core.DragSource;
	import mx.managers.DragManager;
	
	public class WorkNode extends BaseElement
	{	
		public static const AnchorLen:int = 10;
		
		public var shape:Rectangle;
		private var moveOffset:Point;
		public var inputLinks:ArrayCollection;
		public var outputLinks:ArrayCollection;
		
		public function WorkNode(type:int = ElementType.TASK)
		{
			super(type);
		}
		
		override protected function init():void
		{
			super.init();
			this.moveOffset = new Point();
			this.status = StatusType.NODE_NORMAL;
			this.explicitMinHeight = 30;
			this.explicitMinWidth = 30;
			this.shape = new Rectangle();
			this.inputLinks = new ArrayCollection();
			this.outputLinks = new ArrayCollection();
			this.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
			this.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
			this.addEventListener(MouseEvent.CLICK, mouseClickHandler);
			this.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			this.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}
		
		override public function refresh():void
		{
			super.refresh();
			switch(this.status){
				case StatusType.NODE_NORMAL:
					this.skin.currentState = "normal";
					break;
				case StatusType.NODE_RESIZE_HOVER:
					if(canvas.currentElement == null || canvas.currentElement.id != this.id){
						this.status = StatusType.NODE_SELECT;
						//trace(" set to select from resize hover");
						this.skin.currentState = "select";
					}
					else{
						this.skin.currentState = "resize";
					}
					break;
				case StatusType.NODE_RESIZING:
					if(canvas.resizingNode == null || canvas.resizingNode.id != this.id){
						this.status = StatusType.NODE_SELECT;
						this.skin.currentState = "select";
					}
					else{
						this.skin.currentState = "resize";
					}
					break;
				case StatusType.NODE_HOVER:
					this.skin.currentState = "hover";
					break;
				case StatusType.NODE_SELECT:
					this.skin.currentState = "select";
					break;
				case StatusType.NODE_MOVING:
					this.skin.currentState = "move";
					break;
				default:
					this.skin.currentState = "normal";
					break;
			}
			
			for(var i:int = 0; i < this.inputLinks.length; i++){
				FlowLink(this.inputLinks.getItemAt(i)).endNode = this;
			}
			for(i = 0; i < this.outputLinks.length; i++){
				FlowLink(this.outputLinks.getItemAt(i)).startNode = this;
			}
		}
		
		override public function get selected():Boolean
		{
			return this.status == StatusType.NODE_SELECT;
		}
		
		protected function mouseDownHandler(event:MouseEvent):void{
			
		}

		protected function mouseUpHandler(event:MouseEvent):void{
			switch(this.status){
				case StatusType.NODE_MOVING:
					this.status = StatusType.NODE_HOVER;
					break;
				default:
					break;
			}
		}
		
		protected function mouseOverHandler(event:MouseEvent):void{
			switch(canvas.status){
				case StatusType.CANVAS_NORMAL:
				case StatusType.CANVAS_CREATE_ELEMENT:
					switch(this.status){
						case StatusType.NODE_NORMAL:
							this.status = StatusType.NODE_HOVER;
							break;
						default:
							break;
					}					
					break;
				default:
					break;
			}
		}
		
		protected function mouseOutHandler(event:MouseEvent):void{
			switch(canvas.status){
				case StatusType.CANVAS_NORMAL:
				case StatusType.CANVAS_CREATE_ELEMENT:
					switch(this.status){
						case StatusType.NODE_HOVER:
							this.status = StatusType.NODE_NORMAL;
							break;
						default:
							break;
					}			
					break;
				default:
					break;
			}
		}
		
		protected function mouseClickHandler(event:MouseEvent):void{
			switch(canvas.status){
				case StatusType.CANVAS_NORMAL:
					switch(this.status){
						case StatusType.NODE_RESIZING:
						case StatusType.NODE_MOVING:
							break;
						default:					
							trace("node click unselect");
							canvas.unselectAll();
							this.status = StatusType.NODE_SELECT;
							break;
					}					
					break;
				case StatusType.CANVAS_CREATE_ELEMENT:
					if(canvas.tempElement.type == ElementType.LINK){
						if(canvas.tempLink.startNode == null){
							canvas.tempLink.startNode = this;
							canvas.tempLink.status = StatusType.LINE_DRAW;
						}
						else if(canvas.tempLink.endNode == null){
							canvas.tempLink.endNode = this;
							canvas.createLinkByTemp();
						}
					}
					break;
				default:
					break;
			}
			if(this.status == StatusType.NODE_SELECT){
				var e:PropertyEvent = new PropertyEvent("openPropEditor");
				e.elementId = this.id;
				e.elementType = this.type;
				e.owner = this;
				Context.propView.dispatchEvent(e);
			}
		}		
		
		protected function mouseMoveHandler(event:MouseEvent):void{
			this.cursor = MouseCursor.HAND;
			this.anchor = this.getAnchorType(event);
			var p:Point = canvas.getDiagramPoint(event);
			switch(this.status){
				case StatusType.NODE_HOVER:
					if(event.buttonDown){
						this.status = StatusType.NODE_MOVING;
						this.moveOffset.x = p.x - this.x;
						this.moveOffset.y = p.y - this.y;
						break;
					}
					break;
				case StatusType.NODE_SELECT:
					if(event.buttonDown){
						this.status = StatusType.NODE_MOVING;
						this.moveOffset.x = p.x - this.x;
						this.moveOffset.y = p.y - this.y;						
//						var ds:DragSource = new DragSource();
//						ds.addData(new Point(event.localX,event.localY), "dragPoint");
//						DragManager.doDrag(this, ds, event, canvas.snapshoot(this));
//						canvas.movingEles.addItem(this);
//						this.cursor = MouseCursor.HAND;
						break;
					}
					else{
						switch(this.anchor){
							case AnchorType.TOPLEFT:
							case AnchorType.TOPRIGHT:
							case AnchorType.BOTTOMLEFT:
							case AnchorType.BOTTOMRIGHT:												
								this.status = StatusType.NODE_RESIZE_HOVER;
								this.shape.x = this.x;
								this.shape.y = this.y;
								this.shape.width = this.width;
								this.shape.height = this.height;
								break;
							default:
								break;
						}
					}
					break;
				case StatusType.NODE_RESIZE_HOVER:
					switch(this.anchor){
						case AnchorType.TOPLEFT:
						case AnchorType.TOPRIGHT:
						case AnchorType.BOTTOMLEFT:
						case AnchorType.BOTTOMRIGHT:
							if(event.buttonDown){
								this.status = StatusType.NODE_RESIZING;
								canvas.resizingNode = this;
							}
							break;
						default:
							this.status = StatusType.NODE_SELECT;
							break;
					}
					break;
				case StatusType.NODE_MOVING:
					trace("node move unselect");
					canvas.unselectAll(this.id);
					this.move(p.x - this.moveOffset.x, p.y - this.moveOffset.y);
					break;
				default:
					break;
			}
		}
		
		public function getCenterPoint():Point{
			return new Point(this.x + this.width/2, this.y + this.height/2);
		}
		
		public function getLinkPoint(p:Point):Point{
			var lp:Point = new Point();
			var center:Point = this.getCenterPoint();
			switch(this.type){
				case ElementType.START:
				case ElementType.END:
					lp = MathUtil.calcRoundIntersectPoint(center, this.width/2, p);
					break;
				case ElementType.TASK:
					lp = MathUtil.calcEllipseIntersectPoint(center, this.width, this.height, p);
					break;
				case ElementType.PROC:					
					lp = MathUtil.calcRoundRectIntersectPoint(center, this.width, this.height, 20, p);
					//trace(center + "," + p + ",(" + this.width + "," + this.height + ") -> " + lp);
					break;
				default:
					lp = center;
					break;
			}
			return lp;
		}
		
		protected function getAnchorType(event:MouseEvent):int{
			var type:int = AnchorType.NOP;
			var xx:Number = event.localX;
			var yy:Number = event.localY;
			var halfw:Number = this.width/2;
			var halfh:Number = this.height/2;
			var halfAnchorLen:Number = AnchorLen/2;
			if(yy < AnchorLen){
				if(xx < AnchorLen){
					type = AnchorType.TOPLEFT;
				}
				else if(xx > this.width - AnchorLen){
					type = AnchorType.TOPRIGHT;
				}
				else if(xx > halfw-halfAnchorLen && xx < halfw + halfAnchorLen){
					type = AnchorType.TOPMIDDLE;
				}
				else{
					type = AnchorType.OTHER;
				}
			}
			else if(yy > halfh - halfAnchorLen && yy < halfh + halfAnchorLen){
				if(xx < AnchorLen){
					type = AnchorType.CENTERLEFT;
				}
				else if(xx > this.width - AnchorLen){
					type = AnchorType.CENTERRIGHT;
				}
				else if(xx > halfw-halfAnchorLen && xx < halfw + halfAnchorLen){
					type = AnchorType.CENTERMIDDLE;
				}
				else{
					type = AnchorType.OTHER;
				}
			}
			else if(yy > this.height - AnchorLen){
				if(xx < AnchorLen){
					type = AnchorType.BOTTOMLEFT;
				}
				else if(xx > this.width - AnchorLen){
					type = AnchorType.BOTTOMRIGHT;
				}
				else if(xx > halfw-halfAnchorLen && xx < halfw + halfAnchorLen){
					type = AnchorType.BOTTOMMIDDLE;
				}
				else{
					type = AnchorType.OTHER;
				}
			}
			else{
				type = AnchorType.OTHER;
			}
			return type;
		}
	}
}